package com.ruicar.afs.cloud.batch.monthend.process;

import cn.hutool.core.date.DateUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruicar.afs.cloud.batch.dayend.handle.run.SystemJdbcConfig;
import com.ruicar.afs.cloud.batch.frame.AbsBatchRunner;
import com.ruicar.afs.cloud.common.config.VoucherConstant;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.uid.UidGenerator;
import com.ruicar.afs.cloud.common.core.util.SpringContextHolder;
import com.ruicar.afs.cloud.common.modules.constant.VoucherBuriedPointNo;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.sql.*;


/**
 * @author infinity
 * @version 1.0
 * @date 2020/8/18 11:48
 */
@Slf4j
public class VoucherMonthlySubsidySettlementBathRunner extends AbsBatchRunner {
    private SystemJdbcConfig systemJdbcConfig = SpringContextHolder.getBean( SystemJdbcConfig.class );
    private UidGenerator uidGenerator = SpringContextHolder.getBean( UidGenerator.class );

    @Override
    public void process(String param) {
        //发送凭证信息
        log.info( "月结补贴凭证信息--开始" );
        boolean isFinish = false;
        Connection contract = this.getConnection( systemJdbcConfig.getBasic() );
        /***批量日期**/
        Date batchDate = new Date( batchDateInfo.getBatchDate().getTime() );
        while (!isFinish) {
            String loadBreakPoint = loadBreakPoint();
            logger.info( "读取==={}", loadBreakPoint );
            isFinish = handleContractNo( loadBreakPoint, contract, batchDate );
        }
        log.info( "月结补贴凭证信息--结束" );
    }

    private boolean handleContractNo(String loadBreakPoint, Connection contract, Date batchDate) {
        Long id = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        PreparedStatement psf = null;
        PreparedStatement updatePsf = null;
        try {
            id = getId( loadBreakPoint, contract );
            //查询需要生成月结凭证的数据
            StringBuffer sql = new StringBuffer();
            sql.append( "  select   plan.id ,plan.receivable_interest ,plan.contract_no from  basic_cost_amortize_plan plan " );
            sql.append( "  inner join basic_main_info main on main.contract_no=plan.contract_no and main.contract_status in('contractEffective','overdue') " );
            sql.append( "  where     DATE_FORMAT(plan.due_date,'%Y-%m')  = DATE_FORMAT(?,'%Y-%m') " );
            if (id != null) {
                sql.append( "  and  plan.id>? order by plan.id asc  limit 0, ?  " );
            } else {
                sql.append( "  order by plan.id asc  limit 0, ?   " );
            }
            //核算明细
            StringBuffer saveFinanceBusinessAccounting = new StringBuffer();
            saveFinanceBusinessAccounting.append( "insert into basic_business_accounting(id,trans_id,fee_type,buried_point_no,amount,keep_account_date,contract_no,send_status,create_by,create_time  ) " );
            saveFinanceBusinessAccounting.append( "values(?,?,?,?,?,?,?,?,?,?)" );
            ps = contract.prepareStatement( sql.toString() );
            ps.setTimestamp( 1, DateUtil.endOfDay( batchDateInfo.getBatchDate() ).toTimestamp() );
            if (id != null) {
                ps.setLong( 2, id );
                ps.setInt( 3, VoucherConstant.batchesSize );
            } else {
                ps.setInt( 2, VoucherConstant.batchesSize );
            }
            rs = ps.executeQuery();
            psf = contract.prepareStatement( saveFinanceBusinessAccounting.toString() );
            if (rs.next()) {
                rs.previous();
            } else {
                return Boolean.TRUE;
            }
            JSONObject jsonObject = new JSONObject();
            jsonObject.put( "startId", id );
            Long transId = null;
            while (rs != null && rs.next()) {
                id = rs.getLong( "id" );
              String   contractNo = rs.getString( "contract_no" );
                //补贴收入
                BigDecimal cost = rs.getBigDecimal( "receivable_interest" ) != null ? rs.getBigDecimal( "receivable_interest" ) : BigDecimal.ZERO;
                if (cost.compareTo( BigDecimal.ZERO ) != 0) {
                    transId = uidGenerator.getUID();
                    handleInterestIncome( psf, transId, "subsidyIncome", contractNo, cost, VoucherBuriedPointNo.recognitionSubsidyIncome, batchDate );
                }
            }
            psf.executeBatch();
            updatePsf.executeBatch();
            jsonObject.put( "endId", id );
            jsonObject.put( "targetId", transId );
            saveBreakPoint( jsonObject.toString() );
            contract.commit();
        } catch (Exception e) {
            e.printStackTrace();
            throw new AfsBaseException( e.getMessage() );
        } finally {
            clean( ps );
            clean( rs );
            clean( psf );
        }
        return Boolean.FALSE;
    }
    //保存利息收入
    private void handleInterestIncome(PreparedStatement psf, Long transId, String type, String contractNo, BigDecimal receivableInterest, String voucherBuriedPointNo, Date batchDate) throws SQLException {
        if (receivableInterest == null || receivableInterest.compareTo( BigDecimal.ZERO ) == 0) return;
        psf.setLong( 1, transId );
        psf.setLong( 2, transId );
        psf.setString( 3, type );
        psf.setString( 4, AfsEnumUtil.key( voucherBuriedPointNo ) );
        psf.setBigDecimal( 5, receivableInterest );
        psf.setDate( 6, batchDate );
        psf.setString( 7, contractNo );
        psf.setString( 8, "notSend" );
        psf.setString( 9, "system" );
        psf.setDate( 10, batchDate );
        psf.addBatch();
    }

    //获取断点id
    private Long getId(String loadBreakPoint, Connection contract) throws SQLException {
        if (StringUtil.isBlank( loadBreakPoint ))
            return null;
        StringBuffer sql = new StringBuffer();
        sql.append( "select id from  basic_business_accounting where trans_id=? " );
        PreparedStatement ps = contract.prepareStatement( sql.toString() );
        ResultSet rs = null;
        Long id = null;
        JSONObject jsonObject = JSONObject.parseObject( loadBreakPoint );
        Long startId = (Long) jsonObject.get( "startId" );
        Long endId = (Long) jsonObject.get( "endId" );
        Long targetId = (Long) jsonObject.get( "targetId" );
        if (targetId != null) {
            ps.setLong( 1, targetId );
            rs = ps.executeQuery();
            if (rs.next()) {
                id = endId;
            } else {
                id = startId;
            }
        }
        clean( ps );
        clean( rs );
        return id;
    }




}